#pragma once

#include <atomic>
#include <list>
#include <string>
#include <thread>
#include <mutex>
#include <stdio.h>
#include <unistd.h>
#include "fifo_buffer.h"

using namespace std;

#define CLOSE_SOCKET(fd)	close(fd)
typedef int32_t event_fd_def;

typedef void(*IoPortRxCallBackDef)(void* param, const uint8_t *, int32_t);

class BaseIoPort
{
public:
	BaseIoPort(int maxTxFifoSize);
	virtual ~BaseIoPort();

	//以下三个函数创建响应的fd （socket, 或者 file）, 再把fd 添加到 BaseIoPort的fd列表里
	//BaseIoPort只实现了select功能，select为非阻塞io的一种形式，在fd数量比较少时使用方便，
	//fd数量大时，就得使用epoll 
	virtual int32_t Open(string name, int32_t param) = 0;
	virtual int32_t Close() = 0;

	//以下连个为线程的开始和结束，如果不需要特殊实现，请优先使用BaseIoPort里的默认实现
	virtual void Start() ;
	virtual void Stop()  final;
	virtual int32_t ReOpen() final;//fd 关了重开

	inline bool IsOpened() { return mIsOpened; }
	inline void SetupRxCallBack(IoPortRxCallBackDef call_back, void* param) { mRxCallBack = call_back; mRxCallBackParam = param; }
	
	int32_t Send(const uint8_t *data, int32_t len);
protected:
	static bool ProcessLoop();
	static list<BaseIoPort *> mOpenedClientPortList;
	static thread mPortProcessThread;
	static bool mStopProcessFlag;
	static std::mutex mOpenedClientPortListMutex;
	event_fd_def mHandle;
	bool mIsOpened;
	string mName;
	int32_t mParam;
	FifoBuffer *mTxFifo = nullptr;
	IoPortRxCallBackDef mRxCallBack;
	void* mRxCallBackParam = nullptr;
	static event_fd_def mEventHandle;
	bool mIsThreadHaveStart{false};
};